home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fspdev / fspdevControl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  28.3 KB  |  944 lines

  1. /* 
  2.  * fsPdev.c --  
  3.  *
  4.  * Copyright 1987, 1988 Regents of the University of California
  5.  * Permission to use, copy, modify, and distribute this
  6.  * software and its documentation for any purpose and without
  7.  * fee is hereby granted, provided that the above copyright
  8.  * notice appear in all copies.  The University of California
  9.  * makes no representations about the suitability of this
  10.  * software for any purpose.  It is provided "as is" without
  11.  * express or implied warranty.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fspdev/fspdevControl.c,v 9.6 92/10/26 14:05:46 mgbaker Exp $ SPRITE (Berkeley)";
  16. #endif not lint
  17.  
  18. #include <sprite.h>
  19. #include <fs.h>
  20. #include <fsconsist.h>
  21. #include <fsutil.h>
  22. #include <fspdev.h>
  23. #include <fspdevInt.h>
  24. #include <fsNameOps.h>
  25. #include <fsio.h>
  26. #include <fsioLock.h>
  27. #include <fsStat.h>
  28. #include <proc.h>
  29. #include <rpc.h>
  30. #include <fsrecov.h>
  31. #include <recov.h>
  32.  
  33. /*
  34.  *----------------------------------------------------------------------------
  35.  *
  36.  * FspdevControlHandleInit --
  37.  *
  38.  *    Fetch and initialize a control handle for a pseudo-device.
  39.  *
  40.  * Results:
  41.  *    A pointer to the control stream I/O handle.  The found parameter is
  42.  *    set to TRUE if the handle was already found, FALSE if we created it.
  43.  *
  44.  * Side effects:
  45.  *    Initializes and installs the control handle.
  46.  *
  47.  *----------------------------------------------------------------------------
  48.  *
  49.  */
  50. Fspdev_ControlIOHandle *
  51. FspdevControlHandleInit(fileIDPtr, name)
  52.     Fs_FileID *fileIDPtr;
  53.     char *name;
  54. {
  55.     register Boolean found;
  56.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  57.     Fs_HandleHeader *hdrPtr;
  58.  
  59.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fspdev_ControlIOHandle), name,
  60.                 FALSE, &hdrPtr);
  61.     ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
  62.     if (!found) {
  63.     ctrlHandlePtr->serverID = NIL;
  64.     List_Init(&ctrlHandlePtr->queueHdr);
  65.     ctrlHandlePtr->seed = 0;
  66.     List_Init(&ctrlHandlePtr->readWaitList);
  67.     Fsio_LockInit(&ctrlHandlePtr->lock);
  68.     Fsutil_RecoveryInit(&ctrlHandlePtr->rmt.recovery);
  69.     ctrlHandlePtr->accessTime = 0;
  70.     ctrlHandlePtr->modifyTime = 0;
  71.     ctrlHandlePtr->owner.id = (Proc_PID)NIL;
  72.     ctrlHandlePtr->owner.procOrFamily = 0;
  73.     ctrlHandlePtr->prefixPtr = (Fsprefix *)NIL;
  74.     fs_Stats.object.controls++;
  75.     }
  76.     return(ctrlHandlePtr);
  77. }
  78.  
  79. /*
  80.  *----------------------------------------------------------------------
  81.  *
  82.  * FspdevControlIoOpen --
  83.  *
  84.  *    Complete setup of the server's control stream.  Called from
  85.  *    Fs_Open on the host running the server.  We mark the Control
  86.  *    I/O handle as having a server (us).
  87.  * 
  88.  * Results:
  89.  *    SUCCESS.
  90.  *
  91.  * Side effects:
  92.  *    Installs the Control I/O handle and keeps a reference to it.
  93.  *    Marks the process as not suitable for migration.
  94.  *
  95.  *----------------------------------------------------------------------
  96.  */
  97. /*ARGSUSED*/
  98. ReturnStatus
  99. FspdevControlIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  100.          ioHandlePtrPtr)
  101.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  102.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  103.     int            clientID;    /* Host doing the open */
  104.     ClientData        streamData;    /* NIL. */
  105.     char        *name;        /* File name for error msgs */
  106.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  107.                      * I/O to a control stream, or NIL */
  108. {
  109.     register Fspdev_ControlIOHandle    *ctrlHandlePtr;
  110.  
  111.     ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, name);
  112.     if (!List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
  113.     panic( "FsControlStreamCltOpen found control msgs\n");
  114.     }
  115.     ctrlHandlePtr->serverID = clientID;
  116.     *ioHandlePtrPtr = (Fs_HandleHeader *)ctrlHandlePtr;
  117.     /*
  118.      * Can't migrate pseudo-device servers.
  119.      */
  120.     Proc_NeverMigrate(Proc_GetCurrentProc());
  121.     Fsutil_HandleUnlock(ctrlHandlePtr);
  122.     return(SUCCESS);
  123. }
  124.  
  125. /*
  126.  *----------------------------------------------------------------------
  127.  *
  128.  * FspdevControlSelect --
  129.  *
  130.  *    Select on the server's control stream.  This returns readable
  131.  *    if there are control messages in the queue.
  132.  *
  133.  * Results:
  134.  *    SUCCESS.
  135.  *
  136.  * Side effects:
  137.  *    Puts the caller on the handle's read wait list if the control
  138.  *    stream isn't selectable.
  139.  *
  140.  *----------------------------------------------------------------------
  141.  */
  142.  
  143. ReturnStatus
  144. FspdevControlSelect(hdrPtr, waitPtr, readPtr, writePtr, exceptPtr)
  145.     Fs_HandleHeader    *hdrPtr;    /* Handle on device to select */
  146.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  147.     int         *readPtr;    /* Bit to clear if non-readable */
  148.     int         *writePtr;    /* Bit to clear if non-writeable */
  149.     int         *exceptPtr;    /* Bit to clear if non-exceptable */
  150. {
  151.     register Fspdev_ControlIOHandle *ctrlHandlePtr =
  152.         (Fspdev_ControlIOHandle *)hdrPtr;
  153.  
  154.     Fsutil_HandleLock(ctrlHandlePtr);
  155.     if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
  156.     if (waitPtr != (Sync_RemoteWaiter *)NIL) {
  157.         Fsutil_FastWaitListInsert(&ctrlHandlePtr->readWaitList, waitPtr);
  158.     }
  159.     *readPtr = 0;
  160.     }
  161.     *writePtr = *exceptPtr = 0;
  162.     Fsutil_HandleUnlock(ctrlHandlePtr);
  163.     return(SUCCESS);
  164. }
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * FspdevControlRead --
  170.  *
  171.  *    Read from the server's control stream.  The server learns of new
  172.  *    clients by reading this stream.  Internally the stream is a list
  173.  *    of addresses of streams created for the server.  This routine maps
  174.  *    those addresses to streamIDs for the user level server process and
  175.  *    returns them to the reader.
  176.  *
  177.  * Results:
  178.  *    SUCCESS, FS_WOULD_BLOCK,
  179.  *    or an error code from setting up a new stream ID.
  180.  *
  181.  * Side effects:
  182.  *    The server's list of stream ptrs in the process table is updated.
  183.  *
  184.  *----------------------------------------------------------------------
  185.  */
  186. ReturnStatus
  187. FspdevControlRead(streamPtr, readPtr, waitPtr, replyPtr)
  188.     Fs_Stream         *streamPtr;    /* Control stream */
  189.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  190.     Sync_RemoteWaiter    *waitPtr;    /* Process info for remote waiting */
  191.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  192.                      * plus the amount read. */
  193. {
  194.     ReturnStatus         status;
  195.     register Fspdev_ControlIOHandle *ctrlHandlePtr =
  196.         (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
  197.     Pdev_Notify            notify;        /* Message returned to
  198.                          * user-level server proc */
  199.  
  200.     Fsutil_HandleLock(ctrlHandlePtr);
  201.  
  202.     if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
  203.     /*
  204.      * No control messages ready.
  205.      */
  206.     Fsutil_FastWaitListInsert(&ctrlHandlePtr->readWaitList, waitPtr);
  207.     replyPtr->length = 0;
  208.     status = FS_WOULD_BLOCK;
  209.     } else {
  210.     register FspdevNotify *notifyPtr;        /* Internal message */
  211.     notifyPtr = (FspdevNotify *)List_First(&ctrlHandlePtr->queueHdr);
  212.     List_Remove((List_Links *)notifyPtr);
  213.     notify.magic = PDEV_NOTIFY_MAGIC;
  214.     status = Fs_GetStreamID(notifyPtr->streamPtr, ¬ify.newStreamID);
  215.     if (status != SUCCESS) {
  216.         replyPtr->length = 0;
  217.     } else {
  218.         if (readPtr->flags & FS_USER) {
  219.         status = Vm_CopyOut(sizeof(notify), (Address) ¬ify,
  220.                     readPtr->buffer);
  221.         /*
  222.          * No need to close on error because the stream is already
  223.          * installed in the server process's state.  It'll be
  224.          * closed automatically when the server exits.
  225.          */
  226.         } else {
  227.         bcopy((Address)¬ify, readPtr->buffer, sizeof(notify));
  228.         }
  229.         replyPtr->length = sizeof(notify);
  230.     }
  231.     free((Address)notifyPtr);
  232.     }
  233.     Fsutil_HandleUnlock(ctrlHandlePtr);
  234.     return(status);
  235. }
  236.  
  237. /*
  238.  *----------------------------------------------------------------------
  239.  *
  240.  * FspdevControlIOControl --
  241.  *
  242.  *    IOControls for the control stream.
  243.  *
  244.  * Results:
  245.  *    An error code.
  246.  *
  247.  * Side effects:
  248.  *    Command dependent.
  249.  *
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. ReturnStatus
  254. FspdevControlIOControl(streamPtr, ioctlPtr, replyPtr)
  255.     Fs_Stream *streamPtr;        /* I/O handle */
  256.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  257.     Fs_IOReply *replyPtr;        /* Return length and signal */
  258. {
  259.     register Fspdev_ControlIOHandle *ctrlHandlePtr =
  260.         (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
  261.     register ReturnStatus status;
  262.  
  263.     if (ioctlPtr->format != mach_Format) {
  264.     panic("FsControlIOControl: wrong format\n");
  265.     }
  266.     switch(ioctlPtr->command) {
  267.     case IOC_PDEV_SIGNAL_OWNER:
  268.         status = FspdevSignalOwner(ctrlHandlePtr, ioctlPtr);
  269.         break;
  270.     case IOC_REPOSITION:
  271.         status = SUCCESS;
  272.         break;
  273.     case IOC_GET_FLAGS:
  274.         if (ioctlPtr->outBufSize >= sizeof(int)) {
  275.         *(int *)ioctlPtr->outBuffer = 0;
  276.         replyPtr->length = sizeof(int);    /* to quiet lint */
  277.         }
  278.         status = SUCCESS;
  279.         break;
  280.     case IOC_SET_FLAGS:
  281.     case IOC_SET_BITS:
  282.     case IOC_CLEAR_BITS:
  283.         status = SUCCESS;
  284.         break;
  285.     case IOC_TRUNCATE:
  286.         status = SUCCESS;
  287.         break;
  288.     case IOC_LOCK:
  289.     case IOC_UNLOCK:
  290.         Fsutil_HandleLock(ctrlHandlePtr);
  291.         status = Fsio_IocLock(&ctrlHandlePtr->lock, ioctlPtr,
  292.                 &streamPtr->hdr.fileID);
  293.         Fsutil_HandleUnlock(ctrlHandlePtr);
  294.         break;
  295.     case IOC_NUM_READABLE: {
  296.         register int bytesAvailable;
  297.  
  298.         if (ioctlPtr->outBufSize < sizeof(int)) {
  299.         return(GEN_INVALID_ARG);
  300.         }
  301.         Fsutil_HandleLock(ctrlHandlePtr);
  302.         if (List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
  303.         bytesAvailable = 0;
  304.         } else {
  305.         bytesAvailable = sizeof(Pdev_Notify);
  306.         }
  307.         Fsutil_HandleUnlock(ctrlHandlePtr);
  308.         status = SUCCESS;
  309.         *(int *)ioctlPtr->outBuffer = bytesAvailable;
  310.         break;
  311.     }
  312.     case IOC_SET_OWNER:
  313.     case IOC_GET_OWNER:
  314.     case IOC_MAP:
  315.         status = GEN_NOT_IMPLEMENTED;
  316.         break;
  317.     case IOC_PREFIX:
  318.         status = SUCCESS;
  319.         break;
  320.     default:
  321.         status = GEN_INVALID_ARG;
  322.         break;
  323.     }
  324.     return(status);
  325. }
  326.  
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * FspdevControlGetIOAttr --
  331.  *
  332.  *    Called from Fs_GetAttrStream to get the I/O attributes of a
  333.  *    pseudo-device.  The access and modify times of the pseudo-device
  334.  *    are obtained from the internal pdev state.
  335.  *
  336.  * Results:
  337.  *    SUCCESS.
  338.  *
  339.  * Side effects:
  340.  *    None.
  341.  *
  342.  *----------------------------------------------------------------------
  343.  */
  344. ReturnStatus
  345. FspdevControlGetIOAttr(fileIDPtr, clientID, attrPtr)
  346.     register Fs_FileID        *fileIDPtr;    /* Identfies pdev connection */
  347.     int                clientID;    /* Host ID of process asking
  348.                          * for the attributes */
  349.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  350. {
  351.     Fspdev_ControlIOHandle        *ctrlHandlePtr;
  352.  
  353.     ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
  354.     if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
  355.     printf( "FspdevControlGetIOAttr, no %s handle <%d,%x,%x> client %d\n",
  356.         Fsutil_FileTypeToString(fileIDPtr->type), fileIDPtr->serverID,
  357.         fileIDPtr->major, fileIDPtr->minor, clientID);
  358.     return(FS_FILE_NOT_FOUND);
  359.     }
  360.  
  361.     if (ctrlHandlePtr->accessTime > 0) {
  362.     attrPtr->accessTime.seconds = ctrlHandlePtr->accessTime;
  363.     }
  364.     if (ctrlHandlePtr->modifyTime > 0) {
  365.     attrPtr->dataModifyTime.seconds = ctrlHandlePtr->modifyTime;
  366.     }
  367.  
  368.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  369.     return(SUCCESS);
  370. }
  371.  
  372. /*
  373.  *----------------------------------------------------------------------
  374.  *
  375.  * FspdevControlSetIOAttr --
  376.  *
  377.  *    Set the IO attributes of a pseudo-device.
  378.  *
  379.  * Results:
  380.  *    An error code.
  381.  *
  382.  * Side effects:
  383.  *    Updates the access and modify times kept in the pdev state.
  384.  *
  385.  *----------------------------------------------------------------------
  386.  */
  387. ReturnStatus
  388. FspdevControlSetIOAttr(fileIDPtr, attrPtr, flags)
  389.     register Fs_FileID        *fileIDPtr;    /* Identfies pdev connection */
  390.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  391.     int                flags;        /* Tells which attrs to set */
  392. {
  393.     Fspdev_ControlIOHandle        *ctrlHandlePtr;
  394.  
  395.     ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
  396.     if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
  397.     printf( "FspdevControlSetIOAttr, no handle <%d,%d,%x,%x>\n",
  398.         fileIDPtr->serverID, fileIDPtr->type,
  399.         fileIDPtr->major, fileIDPtr->minor);
  400.     return(FS_FILE_NOT_FOUND);
  401.     }
  402.     if (flags & FS_SET_TIMES) {
  403.     ctrlHandlePtr->accessTime = attrPtr->accessTime.seconds;
  404.     ctrlHandlePtr->modifyTime = attrPtr->dataModifyTime.seconds;
  405.     }
  406.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  407.     return(SUCCESS);
  408. }
  409.  
  410. /*
  411.  *----------------------------------------------------------------------
  412.  *
  413.  * FspdevControlVerify --
  414.  *
  415.  *    This is called during recovery.
  416.  *    When the server at a remote site reopens its control stream it
  417.  *    contacts the file server to re-establish itself as the server.
  418.  *    This procedure is called from Fsio_StreamReopen to get the control
  419.  *    handle associated with the top-level shadow stream here at the
  420.  *    file server.
  421.  *
  422.  * Results:
  423.  *    A pointer to the control I/O handle, or NIL if the server is bad.
  424.  *
  425.  * Side effects:
  426.  *    The handle is returned locked and with its refCount incremented.
  427.  *    It should be released with Fsutil_HandleRelease.
  428.  *
  429.  *----------------------------------------------------------------------
  430.  */
  431.  
  432. Fs_HandleHeader *
  433. FspdevControlVerify(fileIDPtr, pdevServerHostID, domainTypePtr)
  434.     Fs_FileID    *fileIDPtr;        /* control I/O file ID */
  435.     int        pdevServerHostID;    /* Host ID of the client */
  436.     int         *domainTypePtr;     /* Return - FS_PSEUDO_DOMAIN */
  437. {
  438.     register Fspdev_ControlIOHandle    *ctrlHandlePtr;
  439.     int serverID = -1;
  440.  
  441.     ctrlHandlePtr = Fsutil_HandleFetchType(Fspdev_ControlIOHandle, fileIDPtr);
  442.     if (ctrlHandlePtr != (Fspdev_ControlIOHandle *)NIL) {
  443.     if (ctrlHandlePtr->serverID != pdevServerHostID) {
  444.         serverID = ctrlHandlePtr->serverID;
  445.         Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  446.         ctrlHandlePtr = (Fspdev_ControlIOHandle *)NIL;
  447.     }
  448.     }
  449.     if (ctrlHandlePtr == (Fspdev_ControlIOHandle *)NIL) {
  450.     printf("FspdevControlVerify, server mismatch (%d not %d) for %s <%x,%x>\n",
  451.         pdevServerHostID, serverID, Fsutil_FileTypeToString(fileIDPtr->type),
  452.         fileIDPtr->major, fileIDPtr->minor);
  453.     }
  454.     if (domainTypePtr != (int *)NIL) {
  455.     *domainTypePtr = FS_PSEUDO_DOMAIN;
  456.     }
  457.     return((Fs_HandleHeader *)ctrlHandlePtr);
  458. }
  459.  
  460. /*
  461.  *----------------------------------------------------------------------
  462.  *
  463.  * FspdevControlReopen --
  464.  *
  465.  *    Reopen a control stream.  A control handle is kept on both the
  466.  *    file server as well as the pseudo-device server's host.  If the
  467.  *    file server reboots a reopen has to be done in order to set
  468.  *    the serverID field on the file server so subsequent client opens work.
  469.  *    Thus this is called on a remote client to contact the file server,
  470.  *    and then on the file server from the RPC stub.
  471.  *
  472.  * Results:
  473.  *    SUCCESS if there is no conflict with the server reopening.
  474.  *
  475.  * Side effects:
  476.  *    On the file server the serverID field is set.
  477.  *
  478.  *----------------------------------------------------------------------
  479.  */
  480. /*ARGSUSED*/
  481. ReturnStatus
  482. FspdevControlReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  483.     Fs_HandleHeader    *hdrPtr;
  484.     int            clientID;        /* ID of pdev server's host */
  485.     ClientData        inData;            /* FspdevControlReopenParams */
  486.     int            *outSizePtr;        /* IGNORED */
  487.     ClientData        *outDataPtr;        /* IGNORED */
  488.  
  489. {
  490.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  491.     register FspdevControlReopenParams *reopenParamsPtr;
  492.     register ReturnStatus status = SUCCESS;
  493.     Fsrecov_HandleState    recovInfo;
  494.  
  495.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  496.     /*
  497.      * Called on the pdev server's host to contact the remote
  498.      * file server and re-establish state.
  499.      */
  500.     Fspdev_ControlIOHandle *ctrlHandlePtr;
  501.     FspdevControlReopenParams params;
  502.     int outSize = 0;
  503.  
  504.     ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
  505.     reopenParamsPtr = ¶ms;
  506.     reopenParamsPtr->fileID = hdrPtr->fileID;
  507.     reopenParamsPtr->serverID = ctrlHandlePtr->serverID;
  508.     reopenParamsPtr->seed = ctrlHandlePtr->seed;
  509.     status = FsrmtReopen(hdrPtr, sizeof(FspdevControlReopenParams),
  510.         (Address)reopenParamsPtr, &outSize, (Address)NIL);
  511.     } else {
  512.     /*
  513.      * Called on the file server to re-establish a control handle
  514.      * that corresponds to a control handle on the pdev server's host.
  515.      */
  516.  
  517.     reopenParamsPtr = (FspdevControlReopenParams *)inData;
  518.     ctrlHandlePtr = FspdevControlHandleInit(&reopenParamsPtr->fileID,
  519.                         (char *)NIL);
  520.  
  521.     /*
  522.      * If we're the name server and we're not the client trying to
  523.      * reopen its control stream, then this is a control stream that
  524.      * we should have in the recovery box.  In this case, clientID is
  525.      * the ID of the machine running the pdev server.  The second case
  526.      * here (after the ||) is due to network partition and we still think
  527.      * we know who the pdev server machine should be.
  528.      */
  529.     if (fsrecov_AlreadyInit && clientID != rpc_SpriteID) {
  530.         Fs_FileID    fid;
  531.  
  532.         fid = reopenParamsPtr->fileID;
  533.         /* Get info from recov box. */
  534.         printf("FspdevControlReopen: checking control %d.%d.%d.%d\n",
  535.             fid.type, fid.serverID, fid.major, fid.minor);
  536.         if (Fsrecov_GetHandle(fid, clientID, &recovInfo, TRUE) != SUCCESS) {
  537.         panic(
  538.         "FspdevControlReopen: couldn't get recov info for handle.");
  539.         }
  540.         /* Test for sameness. */
  541.         if ((recovInfo.fileID.major != fid.major) ||
  542.             (recovInfo.fileID.minor != fid.minor)) {
  543.         panic(
  544.         "FspdevControlReopen: major or minor numbers disagree.");
  545.         }
  546.         if (recovInfo.info != reopenParamsPtr->serverID) {
  547.         if (reopenParamsPtr->serverID == NIL) {
  548.             panic(
  549.             "FspdevControlReopen: serverID disagrees - now NIL.\n");
  550.             /* XXX Update handle here if I get rid of code below. */
  551.         } else {
  552.             panic("FspdevControlReopen: serverID disagrees.");
  553.         }
  554.         }
  555.         if (recovInfo.clientData != reopenParamsPtr->seed) {
  556.         panic("FspdevControlReopen: seed disagrees.");
  557.         }
  558.         /*
  559.          * If we're supposed to have recovered everything from the
  560.          * recov box, then just return here.
  561.          */
  562.         if (fsrecov_FromBox) {
  563.         return SUCCESS;
  564.         }
  565.     }
  566.  
  567.     if (reopenParamsPtr->serverID != NIL) {
  568.         /*
  569.          * The remote host thinks it is running the pdev server process.
  570.          */
  571.         if (ctrlHandlePtr->serverID == NIL) {
  572.         ctrlHandlePtr->serverID = reopenParamsPtr->serverID;
  573.         ctrlHandlePtr->seed = reopenParamsPtr->seed;
  574.         } else if (ctrlHandlePtr->serverID != clientID) {
  575.         printf(
  576.             "PdevControlReopen conflict, %d lost to %d, %s <%x,%x>\n",
  577.             clientID, ctrlHandlePtr->serverID,
  578.             Fsutil_FileTypeToString(ctrlHandlePtr->rmt.hdr.fileID.type),
  579.             ctrlHandlePtr->rmt.hdr.fileID.major,
  580.             ctrlHandlePtr->rmt.hdr.fileID.minor);
  581.         status = FS_FILE_BUSY;
  582.         }
  583.     } else if (ctrlHandlePtr->serverID == clientID) {
  584.         /*
  585.          * The pdev server closed while we were down or unable
  586.          * to communicate.
  587.          */
  588.         ctrlHandlePtr->serverID = NIL;
  589.  
  590.         if (fsrecov_AlreadyInit && clientID != rpc_SpriteID) {
  591.         recovInfo.info = NIL;
  592.         if (Fsrecov_UpdateHandle(reopenParamsPtr->fileID, clientID,
  593.             &recovInfo) != SUCCESS) {
  594.             panic("FspdevControlReopen: couldn't update handle.");
  595.         }
  596.         }
  597.     }
  598.     if (recov_Transparent && !fsrecov_AlreadyInit &&
  599.         clientID != rpc_SpriteID) {
  600.         Fs_FileID    fid;
  601.  
  602.         fid = reopenParamsPtr->fileID;
  603.         printf(
  604.         "FspdevControlReopen: installing control stream %d.%d.%d.%d\n",
  605.             fid.type, fid.serverID, fid.major, fid.minor);
  606.         if (Fsrecov_AddHandle((Fs_HandleHeader *) ctrlHandlePtr,
  607.             (Fs_FileID *) NIL,
  608.             clientID, ctrlHandlePtr->serverID == NIL ? NIL : 0,
  609.             ctrlHandlePtr->seed, TRUE) != SUCCESS) {
  610.         /* We'll have to do better than this! */
  611.         panic("FspdevControlReopen: couldn't add handle to recov box.");
  612.         }
  613.         /* Stream is added in stream reopen procedure. */
  614.     }
  615.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  616.     }
  617.     return(status);
  618. }
  619.  
  620. /*
  621.  *----------------------------------------------------------------------
  622.  *
  623.  * FspdevControlClose --
  624.  *
  625.  *    Close a server process's control stream.  After this the pseudo-device
  626.  *    is no longer active and client operations will fail.
  627.  *
  628.  * Results:
  629.  *    SUCCESS.
  630.  *
  631.  * Side effects:
  632.  *    Reset the control handle's serverID.
  633.  *    Clears out the state for the control message queue.
  634.  *
  635.  *----------------------------------------------------------------------
  636.  */
  637. /*ARGSUSED*/
  638. ReturnStatus
  639. FspdevControlClose(streamPtr, clientID, procID, flags, size, data)
  640.     Fs_Stream        *streamPtr;    /* Control stream */
  641.     int            clientID;    /* HostID of client closing */
  642.     Proc_PID        procID;        /* ID of closing process */
  643.     int            flags;        /* Flags from the stream being closed */
  644.     int            size;        /* Should be zero */
  645.     ClientData        data;        /* IGNORED */
  646. {
  647.     register Fspdev_ControlIOHandle *ctrlHandlePtr =
  648.         (Fspdev_ControlIOHandle *)streamPtr->ioHandlePtr;
  649.     register FspdevNotify *notifyPtr;
  650.     int extra = 0;
  651.     Fsrecov_HandleState    recovInfo;
  652.  
  653.     /*
  654.      * Close any server streams that haven't been given to
  655.      * the master process yet.
  656.      */
  657.     while (!List_IsEmpty(&ctrlHandlePtr->queueHdr)) {
  658.     notifyPtr = (FspdevNotify *)List_First(&ctrlHandlePtr->queueHdr);
  659.     List_Remove((List_Links *)notifyPtr);
  660.     extra++;
  661.     (void)Fs_Close(notifyPtr->streamPtr);
  662.     free((Address)notifyPtr);
  663.     }
  664.     if (extra) {
  665.     printf( "FspdevControlClose found %d left over messages\n",
  666.             extra);
  667.     }
  668.     /*
  669.      * Reset the pseudo-device server ID, both here and at the name server.
  670.      */
  671.     ctrlHandlePtr->serverID = NIL;
  672.     if (ctrlHandlePtr->rmt.hdr.fileID.serverID != rpc_SpriteID) {
  673.     (void)Fsrmt_Close(streamPtr, rpc_SpriteID, procID, 0, 0,
  674.         (ClientData)NIL);
  675.     } else {
  676.     /*
  677.      * We're the name server and if we weren't the machine running the
  678.      * pdev server process, we must update recov box.
  679.      */
  680.     if (recov_Transparent && clientID != rpc_SpriteID) {
  681.         if (fsrecov_DebugLevel <= 2) {
  682.         printf("FspdevControlClose: closing ctrl handle %d.%d.%d.%d ",
  683.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.type,
  684.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.serverID,
  685.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.major,
  686.             ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.minor);
  687.         printf("for client %d with serverID %d\n", clientID,
  688.             ctrlHandlePtr->serverID);
  689.         }
  690.         /*
  691.          * XXX It seems like we should delete the ctrl handle in the
  692.          * recov box, but we don't since the close doesn't delete
  693.          * it from the handle table.  Is this a bug, or should I
  694.          * continue to mimic it?
  695.          */
  696. #ifdef DONT_MIMIC_PDEV_BUG
  697.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) ctrlHandlePtr,
  698.             clientID, 0) != SUCCESS) {
  699.         /* We'll have to do better than this! */
  700.         panic(
  701.         "FspdevControlClose: couldn't remove handle from recov box.");
  702.         }
  703. #else
  704.         /* Update serverID to be NIL so it matches what's done above. */
  705.         if (Fsrecov_GetHandle(ctrlHandlePtr->rmt.hdr.fileID, clientID,
  706.             &recovInfo, FALSE) != SUCCESS) {
  707.         panic(
  708.         "FspdevControlClose: couldn't get recov info for handle.");
  709.         }
  710.         recovInfo.info = NIL;
  711.         if (Fsrecov_UpdateHandle(ctrlHandlePtr->rmt.hdr.fileID, clientID,
  712.             &recovInfo) != SUCCESS) {
  713.         panic("FspdevControlClose: couldn't update handle.");
  714.         }
  715. #endif DONT_MIMIC_PDEV_BUG
  716.         /* Still allow the stream to close since that's done elsewhere. */
  717.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) streamPtr, clientID,
  718.             streamPtr->flags) != SUCCESS) {
  719.         panic(
  720.         "FspdevControlClose: couldn't remove stream from recov box.");
  721.         }
  722.     }
  723.     }
  724.     Fsutil_WaitListDelete(&ctrlHandlePtr->readWaitList);
  725.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  726.     return(SUCCESS);
  727. }
  728.  
  729. /*
  730.  *----------------------------------------------------------------------
  731.  *
  732.  * FspdevControlClientKill --
  733.  *
  734.  *    See if a crashed client was running a pseudo-device master.
  735.  *
  736.  * Results:
  737.  *    None.
  738.  *
  739.  * Side effects:
  740.  *    Clears the serverID field if it matches the crashed host's ID.
  741.  *    This unlocks the handle before returning.
  742.  *
  743.  *----------------------------------------------------------------------
  744.  */
  745. /*ARGSUSED*/
  746. void
  747. FspdevControlClientKill(hdrPtr, clientID)
  748.     Fs_HandleHeader *hdrPtr;    /* File being killed */
  749.     int        clientID;    /* Client ID to kill. */
  750. {
  751.     register Fspdev_ControlIOHandle *ctrlHandlePtr =
  752.         (Fspdev_ControlIOHandle *)hdrPtr;
  753.  
  754.     if (ctrlHandlePtr->serverID == clientID) {
  755.     ctrlHandlePtr->serverID = NIL;
  756.     if (ctrlHandlePtr->rmt.hdr.fileID.serverID == rpc_SpriteID) {
  757.         /*
  758.          * We're the file server and must update recov box if we
  759.          * weren't the machine running the pdev server process.
  760.          */
  761.         if (recov_Transparent && clientID != rpc_SpriteID) {
  762.         if (fsrecov_DebugLevel <= 2) {
  763.             printf("FspdevControlClientKill: killing ctrl handle ");
  764.             printf("%d.%d.%d.%d for clientID %d\n",
  765.                 ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.type,
  766.                 ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.serverID
  767.                 , ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.major,
  768.                 ((Fs_HandleHeader *) ctrlHandlePtr)->fileID.minor,
  769.                 clientID);
  770.         }
  771.         if (Fsrecov_DeleteHandle((Fs_HandleHeader *) ctrlHandlePtr,
  772.             clientID, 0) != SUCCESS) {
  773.             /* We'll have to do better than this! */
  774.             panic(
  775.         "FspdevControlClientKill: couldn't remove handle from recov box.");
  776.         }
  777.         }
  778.     }
  779.     Fsutil_RecoverySyncLockCleanup(&ctrlHandlePtr->rmt.recovery);
  780.     Fsutil_HandleRemove(ctrlHandlePtr);
  781.     fs_Stats.object.controls--;
  782.     } else {
  783.         Fsutil_HandleUnlock(ctrlHandlePtr);
  784.     }
  785. }
  786.  
  787. /*
  788.  *----------------------------------------------------------------------
  789.  *
  790.  * FspdevControlScavenge --
  791.  *
  792.  *    See if this control stream handle is still needed.
  793.  *
  794.  * Results:
  795.  *    TRUE if the handle was removed.
  796.  *
  797.  * Side effects:
  798.  *    Will remove the handle if there is no server.
  799.  *
  800.  *----------------------------------------------------------------------
  801.  */
  802. Boolean
  803. FspdevControlScavenge(hdrPtr)
  804.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  805. {
  806.     register Fspdev_ControlIOHandle *ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
  807.  
  808.     if (ctrlHandlePtr->serverID == NIL) {
  809.     Fsutil_RecoverySyncLockCleanup(&ctrlHandlePtr->rmt.recovery);
  810.     Fsutil_HandleRemove(ctrlHandlePtr);
  811.     fs_Stats.object.controls--;
  812.     return(TRUE);
  813.     } else {
  814.         Fsutil_HandleUnlock(ctrlHandlePtr);
  815.     return(FALSE);
  816.     }
  817. }
  818.  
  819.  
  820. /*
  821.  *----------------------------------------------------------------------
  822.  *
  823.  * Fspdev_ControlRecovTestUseCount --
  824.  *
  825.  *    For recovery testing, return the use count on the stream's iohandle.
  826.  *
  827.  * Results:
  828.  *    Use count.
  829.  *
  830.  * Side effects:
  831.  *    None.
  832.  *
  833.  *----------------------------------------------------------------------
  834.  */
  835. int
  836. Fspdev_ControlRecovTestUseCount(handlePtr)
  837.     Fspdev_ControlIOHandle     *handlePtr;
  838. {
  839.     return handlePtr->rmt.recovery.use.ref;
  840. }
  841.  
  842.  
  843. /*
  844.  *----------------------------------------------------------------------
  845.  *
  846.  * Fspdev_ControlSetupHandle --
  847.  *
  848.  *    Given a pdev control stream recovery object, setup the necessary handle
  849.  *    state for it.
  850.  *
  851.  * Results:
  852.  *    None.
  853.  *
  854.  * Side effects:
  855.  *    A handle is created in put in the handle table.
  856.  *
  857.  *----------------------------------------------------------------------
  858.  */
  859. ReturnStatus
  860. Fspdev_ControlSetupHandle(recovInfoPtr)
  861.     Fsrecov_HandleState    *recovInfoPtr;
  862. {
  863.     Fs_FileID            fileID;
  864.     int                clientID;
  865.     Fspdev_ControlIOHandle    *ctrlHandlePtr;
  866.  
  867.     if (!recov_Transparent) {
  868.     panic("Fspdev_ControlSetupHandle: shouldn't have been called.");
  869.     }
  870.     clientID = recovInfoPtr->fileID.serverID;
  871.     fileID = recovInfoPtr->fileID;
  872.     fileID.serverID = rpc_SpriteID;
  873.     ctrlHandlePtr = FspdevControlHandleInit(&fileID, (char *) NIL);
  874.     ctrlHandlePtr->serverID = recovInfoPtr->info;
  875.     ctrlHandlePtr->seed = recovInfoPtr->clientData;
  876.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  877.  
  878.     return SUCCESS;
  879. }
  880.  
  881. /*
  882.  *----------------------------------------------------------------------
  883.  *
  884.  * FspdevSetupControlReopen --
  885.  *
  886.  *    Set up the data for an RPC to reopen a control handle.
  887.  *
  888.  * Results:
  889.  *    Return status.
  890.  *
  891.  * Side effects:
  892.  *    Data structure set up.
  893.  *
  894.  *----------------------------------------------------------------------
  895.  */
  896. ReturnStatus
  897. FspdevSetupControlReopen(hdrPtr, paramsPtr)
  898.     Fs_HandleHeader    *hdrPtr;
  899.     Address        paramsPtr;
  900. {
  901.     Fspdev_ControlIOHandle *ctrlHandlePtr;
  902.     FspdevControlReopenParams *reopenParamsPtr;
  903.  
  904.     if (hdrPtr != (Fs_HandleHeader *)NIL) {
  905.     /*
  906.      * Called on the pdev server's host to contact the remote
  907.      * file server and re-establish state.
  908.      */
  909.     ctrlHandlePtr = (Fspdev_ControlIOHandle *)hdrPtr;
  910.     reopenParamsPtr = (FspdevControlReopenParams *) paramsPtr;
  911.     reopenParamsPtr->fileID = hdrPtr->fileID;
  912.     reopenParamsPtr->serverID = ctrlHandlePtr->serverID;
  913.     reopenParamsPtr->seed = ctrlHandlePtr->seed;
  914.     } else {
  915.     panic("FspdevSetupControlReopen called on file server.");
  916.     }
  917.     return SUCCESS;
  918. }
  919.  
  920. /*
  921.  *----------------------------------------------------------------------
  922.  *
  923.  * FspdevFinishControlReopen --
  924.  *
  925.  *    Do post-processing for a device handle after bulk reopen.  There is
  926.  *    none for a pseudo device.
  927.  *
  928.  * Results:
  929.  *    None.
  930.  *
  931.  * Side effects:
  932.  *    None.
  933.  *
  934.  *----------------------------------------------------------------------
  935.  */
  936. void
  937. FspdevFinishControlReopen(hdrPtr, statePtr, status)
  938.     Fs_HandleHeader    *hdrPtr;
  939.     Address        statePtr;
  940.     ReturnStatus    status;
  941. {
  942.     return;
  943. }
  944.